using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Transactions;
using NUnit.Framework;
using Hermes.Framework;
using Hermes.Framework.FileSystem;
using Hermes.Framework.Implementation;
using Hermes.Framework.Implementation.File;
using Hermes.Framework.Implementation.Directory;

namespace Hermes.Framework.Test
{
    [TestFixture]
    public class IncorperatingDatabaseTransactionTest
    {
        protected string sourceFile = @"file://./Resources/source.txt";

        protected string toFile = @"file://./Resources/To/source.txt";

        protected INonTransactableFileSystemFactory factory = null;

        protected IResourceManager resourceManager = null;

        protected ITransactableOperationAbstractFactory transactableOperationFactory = null;

        protected string connectionString = null;

        string updateSql = "update Product set name = 'Duckie' where name = 'Duck';";

        static void Main1()
        {
            IncorperatingDatabaseTransactionTest test = new IncorperatingDatabaseTransactionTest();

            test.TestSuccess();
            test.TestFail();
        }

        public IncorperatingDatabaseTransactionTest()
        {
            factory = new SimpleFileSystemFactory();
            resourceManager = new SimpleResourceManager();

            connectionString = ConfigurationSettings.AppSettings["connectionString"];

            transactableOperationFactory = new SimpleTransactionOperationAbstractFactory();
            transactableOperationFactory.FileSystemFactory = factory;
            transactableOperationFactory.ResourceManager = this.resourceManager;
        }

        [SetUp]
        public void SetUp()
        {

        }

        [TearDown]
        public void TearDown()
        {

        }

        protected int ExecuteTransaction()
        {
            int count = 0;
            SqlConnection connection = null;

            using (TransactionScope scope = new TransactionScope())
            {
                connection = new SqlConnection(connectionString);
                SqlCommand update = new SqlCommand(updateSql, connection);
                update.Connection.Open();

                update.ExecuteNonQuery();

                ITransactableCopy copy = this.transactableOperationFactory.GetCopy(sourceFile, toFile);
                copy.Copy();

                scope.Complete();
            }
            connection.Close();

            using (connection)
            {
                SqlCommand command = new SqlCommand("select count(1) from Product where name = 'Duck'", connection);
                command.Connection.Open();

                count = ((Int32)command.ExecuteScalar());
            }
            connection.Close();

            return count;
        }

        [Test]
        public void TestSuccess()
        {
            INonTransactableFileSystem fileSystem = this.factory.GetFileSystem(sourceFile);
            if (!fileSystem.Exists(sourceFile))
            {
                fileSystem.CreateFile(sourceFile);
            }

            try
            {
                int count = ExecuteTransaction();
                Assert.AreEqual(0, count);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        [Test]
        public void TestFail()
        {
            INonTransactableFileSystem fileSystem = this.factory.GetFileSystem(sourceFile);
            if (fileSystem.Exists(sourceFile))
            {
                fileSystem.Delete(sourceFile);
            }

            try
            {
                int count = ExecuteTransaction();
                Assert.AreEqual(1, count);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }
}
